var listeners = (function() {
	return {
		"onInstalled": function(details) {
			console.log(details);
			if (details.reason == 'update') {
				if (details.previousVersion == "0.3.3") {
					//user is upgrading from 3.3 convert their database from the 
					//local storage format to indexedDB
					chrome.storage.local.get(function(details) { 
						 for (var i in details.links) {
							var ni = new notification_item();
							ni.who = details.links[i]._whoName;
							ni.setLink(details.links[i]._link);
							ni.save();
						 }
					});
				} else if (details.previousVersion == "0.4.1") {
					var ia = [];
					//user is upgrading from 0.41 the database data needs to be converted.
					$.indexedDB(OLD_DB_NAME).objectStore(NOTE_TABLE).each(function(obj) {
						var newItem = new item();
						newItem.create(obj.value.link, obj.value.name, obj.value.text);
						ia.push(JSON.parse(newItem.print()));
					}).done(function() {
						for (var i in ia) {
							$.indexedDB(NEW_DB_NAME).objectStore("Items").add({ uid: ia[i].uid, uname: ia[i].uname, gid: ia[i].gid, type: ia[i].type, text: ia[i].text, link: ia[i].link, timestamp: ia[i].timestamp });
						}
					});
					
					var ha = [];
					$.indexedDB(OLD_DB_NAME).objectStore(HISTORY_TABLE).each(function(obj) {
						var newItem = new item();
						newItem.create(obj.value.link, obj.value.name, '');
						ha.push(JSON.parse(newItem.print()));
					}).done(function() {
						for (var i in ha) {
							$.indexedDB(NEW_DB_NAME).objectStore("History").add({ uid: ha[i].uid, uname: ha[i].uname, gid: ha[i].gid, type: ha[i].type, timestamp: ha[i].timestamp });
						}
					});
					
					$.indexedDB(OLD_DB_NAME).deleteDatabase();
				}
			}
		},
		"onAlarm": function(alarm) {
			log.message('Alarm: ' + alarm.name + ' set for ' + alarm.scheduledTime + ' rang at ' + Date.now());
			if (alarm.name == alarms.type.refresh) {
				startGathering(0)
			} else if (alarm.name == alarms.type.gather) {
				getNoteTab((localStorage["notification_tabId"]) ? Number(localStorage["notification_tabId"]) : 0);
			} else if (alarm.name == alarms.type.process) {
				//it's been 2 mins since last processed.. obviously stalled
				// call next and let message processing clean up or restart
				c_extension.sendMessage({action: 'next'});
			} else if (alarm.name == alarms.type.stalled) {
				getNoteTab(-1);
			} else {
				//unknown alarm?
			}
		},
		"onClicked": function(tab) {
			chrome.browserAction.setPopup({popup: 'notes.html'});
			
			startGathering(0);
		},
		"onMessage": function(request, sender, response) { 
			log.message('Message Recieved from Tab');
			
			//ignore requests from pages/tabs that are still loading?
			if ((sender.tab.status == 'loading') && (state.get() == state.type.gathering)) {
				log.message('Invalid status during Gather, exiting');
				return;
			}
			
			//message has the links container
			if (request.links) {
				alarms.create.gather(2  * ONE_MINUTE);
				log.message('Requesting Note Data');
				state.set(state.type.gathering);
				processDataArray(request.links, sender.tab.id);
			} else if (request.rewards) {
				log.message('Requesting Rewards Data');
				processRewardsArray(request.rewards, sender.tab.id);
			} else if (request.action) {
				if (request.action == 'next') {
					log.message('Requesting next action');
					
					if (state.get() == state.type.processing) {
						//there have been reports of stalling during notification processing
						// but I have been unable to track it down. Experimenting with setting
						// an alarm that is cleared if processing completes
						alarms.create.process(ONE_MINUTE * 2);
						var limit = globalSettings.getSetting("process_limit");
						if (limit > 0) {
							var count = processCount(false);
							log.message('Limit: ' + limit + ', Count: ' + count);
							if (count >= limit) {
								state.set(state.type.stopped);
							}
						}
						if (sender.tab.id >= 1) 
							c_tabs.remove(sender.tab.id);
						processItems(0);
						//alarms.clear(ALARM_PROCESS);
					} else {
						//stop takes precedence over refresh
						if (state.get() == state.type.stopped) {
							log.message('Stopping');
							state.stop();
							return;
						}
						
						// refresh
						if (state.get() == state.type.refresh) {
							log.message('Refreshing');
							//start gathering notes
							startGathering(sender.tab.id);
						}
					}
				} else if (request.action == 'refresh') {
					log.message('refresh action requested');
					if (state.get() == state.type.stopped)  {
						startGathering(sender.tab.id);
					} else {
						state.set(state.type.refresh);
						alarms.create.refresh(.5);
					}
					response({action: 'ok'});
				} else if (request.action == 'stop') {
					log.message('stop action requested');
					state.stop();
					response({action: 'ok'});
				} else if (request.action == 'message') {
					log.message(JSON.stringify(request));
				}
			}
		}
	}
}());

/* LISTENERS */
chrome.runtime.onInstalled.addListener(function(details) {
	listeners.onInstalled(details);
});

c_alarms.onAlarm.addListener(function(alarm) {
	listeners.onAlarm(alarm);
});

//call the script entry point when the Chrome action button is clicked
chrome.browserAction.onClicked.addListener(function(tab) {
	listeners.onClicked(tab);
});

//message listener, waits for messages sent to the extension and executes 
// different actions based on which message the request has
c_extension.onMessage.addListener(function(request, sender, response) {
	listeners.onMessage(request, sender, response);
});

//startGathering(0);